<?php

namespace App\Kuafu\Pay\Service;

use App\Kuafu\Pay\Enum\PayCodeEnum;
use App\Kuafu\Pay\Exceptions\PayException;
use App\Kuafu\Pay\Model\PayStreamModel;

class PayConfigService
{
    // 支付账号 - 公司户
    const COMPANY_TJ_SUPPLER_CHAIN = 1; // 厦门供应链
    const COMPANY_FRIED_IDEA       = 2; // 厦门心有炸念餐饮管理有限公司
    const COMPANY_DIGITAL_TECH     = 3; // 上海万皮思数字科技
    const COMPANY_ALI_SAND         = 4; // 支付宝沙箱
    const COMPANY_HN_FRUIT         = 5; // 河南干果店
    const COMPANY_FOOD_TECH        = 6; // 北京万皮思食品科技-富友
    const COMPANY_XM_SUPPLER_CHAIN = 7; // 厦门供应链-投标用

    const COMPANY_TEXT = [
        self::COMPANY_TJ_SUPPLER_CHAIN => '厦门供应链',
        self::COMPANY_FRIED_IDEA       => '厦门心有炸念',
        self::COMPANY_DIGITAL_TECH     => '上海万皮思数字科技',
        self::COMPANY_ALI_SAND         => '支付宝沙箱',
        self::COMPANY_HN_FRUIT         => '河南干果店',
        self::COMPANY_FOOD_TECH        => '北京万皮思食品科技-富友',
        self::COMPANY_XM_SUPPLER_CHAIN => '厦门供应链-投标用',
    ];

    private int $payChannel;
    private int $sysType;
    private int $shopId;
    private int $company;

    /**
     * @param int $payChannel
     * @param int $sysType
     * @param int $shopId
     * @throws PayException
     */
    public function __construct(int $payChannel, int $sysType, int $shopId, int $forceCompany = 0)
    {
        $this->payChannel = $payChannel;
        $this->sysType    = $sysType;
        $this->shopId     = $shopId;

        if ($forceCompany) {
            $this->company = $forceCompany;

            // 测试环境下，支付宝走沙箱
            if ($this->payChannel == PayStreamModel::PAY_CHANNEL_ALI && isTest()) {
                $this->company = self::COMPANY_ALI_SAND;
            }

        } else {
            $this->company = $this->getCompanyBySysType();

            // 参数校验
            $this->checkParam();
        }
    }

    /**
     * 参数校验，后期变复杂可考虑重构建造成模式
     * @throws PayException
     */
    private function checkParam(): void
    {
        switch ($this->payChannel) {
            case PayStreamModel::PAY_CHANNEL_ALI:
            case PayStreamModel::PAY_CHANNEL_WX:
            case PayStreamModel::PAY_CHANNEL_MYBANK_PAY:
            case PayStreamModel::PAY_CHANNEL_MYBANK_CASHIER_PAY:

                if (!in_array($this->sysType, [
                    PayStreamModel::SYS_TYPE_ROS,
                    PayStreamModel::SYS_TYPE_OPEN_SHOP_LEAGUE,
                    PayStreamModel::SYS_TYPE_OPEN_SHOP_DESIGN,
                    PayStreamModel::SYS_TYPE_OPEN_SHOP_EQUIPMENT,
                    PayStreamModel::SYS_TYPE_OPEN_SHOP_DECORATE,
                    PayStreamModel::SYS_TYPE_ANNUAL_FEE,
                    PayStreamModel::SYS_TYPE_AGAINST,
                    PayStreamModel::SYS_TYPE_WORK_CLOTHES,
                    PayStreamModel::SYS_TYPE_PSI_TENDER,
                ])) {
                    throw new PayException(PayCodeEnum::ERR_PAY_BIZ_CHANNEL);
                }
                break;

            case PayStreamModel::PAY_CHANNEL_CASH:
            case PayStreamModel::PAY_CHANNEL_FY:

                if (!$this->shopId) {
                    throw new PayException(PayCodeEnum::ERR_PAY_BIZ_CHANNEL);
                }
                break;

            default:

                if ($this->payChannel >= PayStreamModel::PAY_CHANNEL_CUSTOM_PAYMENT) {
                    break;
                }

                throw new PayException(PayCodeEnum::ERR_PAY_ERROR_PAY_CHANNEL,
                    PayCodeEnum::CODE_TEXT[PayCodeEnum::ERR_PAY_ERROR_PAY_CHANNEL] . ':' . $this->payChannel);
        }
    }

    /**
     * 通过sysType获取对应公司
     * @return int
     */
    private function getCompanyBySysType(): int
    {
        // 生产环境
        if (config('app.env') == 'prod' || config('app.env') == 'pre') {
//        if (true) {
            switch ($this->sysType) {
                case PayStreamModel::SYS_TYPE_ROS:
                case PayStreamModel::SYS_TYPE_OPEN_SHOP_EQUIPMENT:
                case PayStreamModel::SYS_TYPE_OPEN_SHOP_DECORATE:
                case PayStreamModel::SYS_TYPE_WORK_CLOTHES:
                    $company = self::COMPANY_TJ_SUPPLER_CHAIN;
                    break;
                case PayStreamModel::SYS_TYPE_PSI_TENDER:
                    $company = self::COMPANY_XM_SUPPLER_CHAIN;
                    break;
                case PayStreamModel::SYS_TYPE_OPEN_SHOP_LEAGUE:
                case PayStreamModel::SYS_TYPE_OPEN_SHOP_DESIGN:
                case PayStreamModel::SYS_TYPE_ANNUAL_FEE:
                case PayStreamModel::SYS_TYPE_AGAINST:
                    $company = self::COMPANY_FRIED_IDEA;
                    break;
                case PayStreamModel::SYS_TYPE_RMS_MEAL:
                case PayStreamModel::SYS_TYPE_RMS_COUPON_PACKAGE:
                    $company = self::COMPANY_FOOD_TECH;
                    break;
                default:
                    $company = 0;
                    break;
            }

            return $company;
        }

        // 测试环境
        if (!in_array($this->sysType, array_keys(PayStreamModel::SYS_TYPE_TEXT))) {
            return 0;
        }

        // 阿里的都走沙箱
        if ($this->payChannel == PayStreamModel::PAY_CHANNEL_ALI) {
            return self::COMPANY_ALI_SAND;
        }

        // 微信都走数科
        return self::COMPANY_DIGITAL_TECH;
    }

    /**
     * 根据入参组合，获取支付配置参数
     * @return array
     */
    public function getPayConfig(): array
    {
//        if (!$this->company) {
//            throw new PayException(PayCodeEnum::ERR_PAY_COMPANY);
//        }
        $config = [];
        switch ($this->payChannel) {
            case PayStreamModel::PAY_CHANNEL_ALI:
                $config                   = config('pay.ali.company.' . $this->company);
                $config['companyAccount'] = $config['appId'];
                break;
            case PayStreamModel::PAY_CHANNEL_WX:
                $config                   = config('pay.wx.company.' . $this->company);
                $config['companyAccount'] = $config['mch_id'];
                break;
            case PayStreamModel::PAY_CHANNEL_CASH:
//            case $this->payChannel >= PayStreamModel::PAY_CHANNEL_CUSTOM_PAYMENT:
                $config['companyAccount'] = '';
                break;
            case PayStreamModel::PAY_CHANNEL_FY:
                $config                   = ShopPayService::getPayConfigCache($this->shopId, $this->payChannel);
                $config['companyAccount'] = $config['mch_id'] ?? '';
                break;
            case PayStreamModel::PAY_CHANNEL_MYBANK_PAY:// 网商支付
            case PayStreamModel::PAY_CHANNEL_MYBANK_CASHIER_PAY:// 网商小程序支付
                $getOrderAccount          = ShopPayService::getOrderAccount($this->payChannel, $this->company);
                $config['companyAccount'] = $getOrderAccount['payeeId'] ?? '';
                $config['payeeType']      = $getOrderAccount['payeeType'] ?? '';
                break;
            default:
                $config['companyAccount'] = '';
        }

        if (!$config) {
            throw new PayException(PayCodeEnum::ERR_PAY_BIZ_CHANNEL);
        }

        $config['company'] = $this->company;

        return $config;
    }
}
